from datetime import datetime
import time
from typing import List

import pydantic
from sqlalchemy import insert, select, update

from forward.api.admin.schemas.system import (
    SystemAuthDeptAddInSchema,
    SystemAuthDeptEditInSchema,
    SystemAuthDeptOutSchema,
    SystemAuthDeptListInSchema,
)
from forward.dependencies.database import db
from forward.model.tables import SystemAuthDeptModel
from forward.utils.array import ArrayUtil


class SystemAuthDeptService:

    async def fetch_all(self):
        dept_all_record = await db.fetch_all(
            select(SystemAuthDeptModel)
            .where(SystemAuthDeptModel.pid >= 0, SystemAuthDeptModel.is_delete == 0)
            .order_by(SystemAuthDeptModel.sort)
        )
        # return pydantic.parse_obj_as(List[SystemAuthDeptOutSchema], dept_all)
        return [SystemAuthDeptOutSchema.model_validate(i) for i in dept_all_record]

    async def fetch_list(self, dept_list_in: SystemAuthDeptListInSchema):
        name = dept_list_in.name
        is_stop = dept_list_in.is_stop
        where = [SystemAuthDeptModel.is_delete == 0]
        if name:
            where.append(SystemAuthDeptModel.name.like("%{0}%".format(name)))
        if is_stop is not None:
            where.append(SystemAuthDeptModel.is_stop == is_stop)
        depts_record = await db.fetch_all(
            select(SystemAuthDeptModel)
            .select_from(SystemAuthDeptModel)
            .where(*where)
            .order_by(SystemAuthDeptModel.sort)
        )
        auth_depts = [
            SystemAuthDeptOutSchema.model_validate(i, from_attributes=True).model_dump(
                by_alias=True
            )
            for i in depts_record
        ]
        return ArrayUtil.list_to_tree(
            auth_depts,  # type: ignore
            "id",
            "pid",
            "children",
        )

    async def add(self, dept_add_in: SystemAuthDeptAddInSchema):
        if dept_add_in.pid == 0:
            assert not await db.fetch_one(
                select(SystemAuthDeptModel).where(
                    SystemAuthDeptModel.pid == 0, SystemAuthDeptModel.is_delete == 0
                )
            ), "顶级部门只允许有一个"
        create_dept = dept_add_in.model_dump()

        query = insert(SystemAuthDeptModel).values(**create_dept)
        return await db.execute(query)

    async def edit(self, dept_edit_in: SystemAuthDeptEditInSchema):
        edit_dept_record = await db.fetch_one(
            select(SystemAuthDeptModel).where(
                SystemAuthDeptModel.id == dept_edit_in.id,
                SystemAuthDeptModel.is_delete == 0,
            )
        )
        assert edit_dept_record, "部门不存在"
        edit_dept = SystemAuthDeptOutSchema.model_validate(
            edit_dept_record, from_attributes=True
        )

        assert not (edit_dept.pid == 0 and dept_edit_in.pid > 0), "顶级部门不能修改上级"
        assert not (dept_edit_in.pid == dept_edit_in.id), "上级部门不能是自己"

        edit_post = dept_edit_in.model_dump()
        return await db.execute(
            update(SystemAuthDeptModel)
            .where(SystemAuthDeptModel.id == dept_edit_in.id)
            .values(**edit_post)
        )

    async def delete(self, dept_id: int):
        del_dept_record = await db.fetch_one(
            select(SystemAuthDeptModel).where(
                SystemAuthDeptModel.id == dept_id,
                SystemAuthDeptModel.is_delete == 0,
            )
        )
        del_dept = SystemAuthDeptOutSchema.model_validate(
            del_dept_record, from_attributes=True
        )
        assert del_dept, "部门不存在"
        assert del_dept.pid != 0, "顶级部门不能删除"

        del_dept_child = await db.fetch_one(
            select(SystemAuthDeptModel).where(
                SystemAuthDeptModel.pid == dept_id,
                SystemAuthDeptModel.is_delete == 0,
            )
        )

        assert not del_dept_child, "请先删除子级部门"

        return await db.execute(
            update(SystemAuthDeptModel)
            .where(SystemAuthDeptModel.id == dept_id)
            .values(is_delete=1, deleted_time=datetime.now())
        )

    async def detail(self, dept_id: int):
        post_detail = await db.fetch_one(
            select(SystemAuthDeptModel).where(
                SystemAuthDeptModel.id == dept_id,
                SystemAuthDeptModel.is_delete == 0,
            )
        )
        assert post_detail, "部门已不存在"

        return SystemAuthDeptOutSchema.model_validate(
            post_detail, from_attributes=True
        ).model_dump(by_alias=True)

    @classmethod
    async def instance(cls):
        return cls()
